import { Module, DynamicModule } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AuthService } from './services/auth.service';
import { JwtStrategy } from './strategies/jwt.strategy';
import { JwtAuthGuard } from './guards/jwt-auth.guard';
import { RolesGuard } from './guards/roles.guard';

export interface AuthModuleOptions {
  jwtSecret?: string;
  jwtExpiresIn?: string;
  jwtRefreshExpiresIn?: string;
}

@Module({})
export class AuthModule {
  static forRoot(options?: AuthModuleOptions): DynamicModule {
    return {
      module: AuthModule,
      imports: [
        PassportModule.register({ defaultStrategy: 'jwt' }),
        JwtModule.registerAsync({
          imports: [ConfigModule],
          useFactory: async (configService: ConfigService) => ({
            secret: options?.jwtSecret || configService.get<string>('JWT_SECRET', '$%^ad123'),
            signOptions: {
              expiresIn: options?.jwtExpiresIn || configService.get<string>('JWT_EXPIRES_IN', '1d'),
            },
          }),
          inject: [ConfigService],
        }),
      ],
      providers: [
        AuthService,
        JwtStrategy,
        JwtAuthGuard,
        RolesGuard,
      ],
      exports: [
        AuthService,
        JwtAuthGuard,
        RolesGuard,
        PassportModule,
        JwtModule,
      ],
    };
  }

  static forRootAsync(options: {
    useFactory: (...args: any[]) => Promise<AuthModuleOptions> | AuthModuleOptions;
    inject?: any[];
    imports?: any[];
  }): DynamicModule {
    return {
      module: AuthModule,
      imports: [
        PassportModule.register({ defaultStrategy: 'jwt' }),
        JwtModule.registerAsync({
          imports: [ConfigModule, ...(options.imports || [])],
          useFactory: async (configService: ConfigService, ...args: any[]) => {
            const authOptions = await options.useFactory(...args);
            return {
              secret: authOptions?.jwtSecret || configService.get<string>('JWT_SECRET', 'your-secret-key'),
              signOptions: {
                expiresIn: authOptions?.jwtExpiresIn || configService.get<string>('JWT_EXPIRES_IN', '1d'),
              },
            };
          },
          inject: [ConfigService, ...(options.inject || [])],
        }),
      ],
      providers: [
        AuthService,
        JwtStrategy,
        JwtAuthGuard,
        RolesGuard,
      ],
      exports: [
        AuthService,
        JwtAuthGuard,
        RolesGuard,
        PassportModule,
        JwtModule,
      ],
    };
  }
}
